package com.cpit.qualitycontrol.dao.jpqlquery;

import com.cpit.qualitycontrol.entity.ProcessRule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.TypedQuery;
import java.util.Iterator;
import java.util.List;

/**
 *
 * @author Hull
 * @date 2017/10/9
 * 流程规则可变条件查询仓库类
 */
@Component
public class ProcessRuleQueryRepository {
    @Autowired
    private EntityManagerFactory entityManagerFactory = null;

    /**
     * 根据可变条件查询流程规则对应的分页
     * @param name 流程规则名称
     * @param deviceTypeId 设备类型ID
     * @param workOrderTypeId 工单类型ID
     * @param pageable 分页排序条件
     * @param projectIds
     * @return 符合查询条件的流程规则分页对象
     */
    public Page<ProcessRule> findByCondition(String name, Long deviceTypeId, Long workOrderTypeId, Long projectId, Pageable pageable, String projectIds){
        EntityManager entityManager = entityManagerFactory.createEntityManager();

        //查询记录总数
        String strJpqlCountSql = getJpqlCountSqlFixCondition().append(getSqlPartOfCondition(name, deviceTypeId, workOrderTypeId, projectId, projectIds)).toString();
        Long recordCount = (Long) entityManager.createQuery(strJpqlCountSql).getSingleResult();

        //分页查询
        String strJpqlSql = getJpqlSqlFixCondition().append(getSqlPartOfCondition(name, deviceTypeId, workOrderTypeId, projectId, projectIds)).append(getSqlPartOfOrderBy(pageable)).toString();
        TypedQuery<ProcessRule> typedQuery = entityManager.createQuery(strJpqlSql, ProcessRule.class);
        typedQuery.setMaxResults(pageable.getPageSize());
        typedQuery.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());

        return new PageImpl<>(typedQuery.getResultList(), pageable, recordCount);
    }

    /**
     * 根据可变条件查询流程规则列表
     * @param name 流程规则名称
     * @param deviceTypeId 设备类型ID
     * @param workOrderTypeId 工单类型ID
     * @param projectId 项目ID
     * @return 符合查询条件的流程规则列表
     */
    public List<ProcessRule> findByCondition(String name, Long deviceTypeId, Long workOrderTypeId, Long projectId){
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        String strJpql = getJpqlSqlFixCondition().append(getSqlPartOfCondition(name, deviceTypeId, workOrderTypeId, projectId, null)).toString();
        TypedQuery<ProcessRule> typedQuery = entityManager.createQuery(strJpql, ProcessRule.class);

        return typedQuery.getResultList();
    }

    /**
     * 根据主键ID查询流程规则
     * @param id 主键ID
     * @return 流程规则对象
     */
    public ProcessRule findById(Long id){
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        String strJpql = getJpqlSqlFixCondition().append(" and pr.id = ").append(id).toString();
        TypedQuery<ProcessRule> typedQuery = entityManager.createQuery(strJpql, ProcessRule.class);

        return typedQuery.getSingleResult();
    }

    /**
     * 根据可变条件查询流程规则列表
     * @param deviceTypeId 设备类型ID
     * @param workOrderTypeIds 工单类型IDs，逗号分隔
     * @param projectId 项目ID
     * @return 符合查询条件的流程规则列表
     */
    public List<ProcessRule> findByDeviceTypeOrderTypesProject(Long deviceTypeId, String workOrderTypeIds, Long projectId){
        char chDouHao = ',';
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        StringBuilder sbJpql = getJpqlSqlFixCondition().append(" and pr.deviceTypeId = ").append(deviceTypeId)
                .append(" and pr.projectId = ").append(projectId)
                .append(" and pr.workOrderTypeId in (").append(workOrderTypeIds.trim());
        if (sbJpql.charAt(sbJpql.length()-1) == chDouHao) {
            sbJpql.setLength(sbJpql.length() - 1);
        }
        sbJpql.append(")");

        TypedQuery<ProcessRule> typedQuery = entityManager.createQuery(sbJpql.toString(), ProcessRule.class);

        return typedQuery.getResultList();
    }

    /**
     * 生成含固定条件查询记录的JPQL语句
     * @return JPQL语句字符串对象
     */
    private StringBuilder getJpqlSqlFixCondition() {
        return new StringBuilder("SELECT new com.cpit.qualitycontrol.entity.ProcessRule(pr.id, pr.name, pr.description, pr.deviceTypeId, dt.name, " +
                "pr.workOrderTypeId, wot.name, pr.photoCount, pr.projectId, pj.name, pr.additionalBusinessId)")
                .append(" from ProcessRule pr, DeviceType dt, WorkOrderType wot, Project pj ")
                .append(" where pr.deviceTypeId=dt.id and pr.workOrderTypeId=wot.id and pr.projectId=pj.id");
    }

    /**
     * 生成含固定条件查询记录数量的JPQL语句
     * @return JPQL语句字符串对象
     */
    private StringBuilder getJpqlCountSqlFixCondition() {
        return new StringBuilder("SELECT count(pr)")
                .append(" from ProcessRule pr, DeviceType dt, WorkOrderType wot, Project pj ")
                .append(" where pr.deviceTypeId=dt.id and pr.workOrderTypeId=wot.id and pr.projectId=pj.id");
    }

    /**
     * 生成动态可变条件部分字符串
     * @param name 流程规则名称
     * @param deviceTypeId 设备类型ID
     * @param workOrderTypeId 工单类型ID
     * @param projectId 项目ID
     * @param projectIds
     * @return 可变条件字符串对象
     */
    private StringBuilder getSqlPartOfCondition(String name, Long deviceTypeId, Long workOrderTypeId, Long projectId, String projectIds) {
        StringBuilder sbCondition = new StringBuilder("");
        if (name != null && !name.isEmpty()) {
            sbCondition.append(" and pr.name like '%").append(name).append("%'");
        }
        if (deviceTypeId != null && deviceTypeId != 0) {
            sbCondition.append(" and pr.deviceTypeId = ").append(deviceTypeId);
        }
        if (workOrderTypeId != null && workOrderTypeId != 0) {
            sbCondition.append(" and pr.workOrderTypeId = ").append(workOrderTypeId);
        }
        if (projectId != null && projectId != 0) {
            sbCondition.append(" and pr.projectId = ").append(projectId);
        }
        if(projectIds!=null &&projectIds.length()>0){
            sbCondition.append(" and  pr.projectId in (").append(projectIds.trim()).append(")");
        }

        return sbCondition;
    }

    /**
     * 生成JPQL语句中排序部分
     * @param pageable 含排序的分页对象Pageable对象
     * @return 排序部分字符串对象
     */
    private StringBuilder getSqlPartOfOrderBy(Pageable pageable) {
        final String strOrderBy = " order by ";
        final String strDouHao = ",";
        StringBuilder stringBuilder = new StringBuilder("");

        Sort sort = pageable.getSort();
        if(sort != null) {
            stringBuilder.append(strOrderBy);
            Iterator<Sort.Order> iterator = sort.iterator();
            while(iterator.hasNext()) {
                Sort.Order order = iterator.next();
                if(order == null) {
                    break;
                }
                String orderProperty = order.getProperty();
                switch (orderProperty) {
                    case "deviceTypeName":
                        stringBuilder.append("dt.name");
                        break;
                    case "workOrderTypeName":
                        stringBuilder.append("wot.name");
                        break;
                    case "projectName":
                        stringBuilder.append("pj.name");
                        break;
                    default:
                        stringBuilder.append("pr.").append(orderProperty);
                        break;
                }
                stringBuilder.append(" ").append(order.getDirection().name()).append(",");
            }
        }
        if(stringBuilder.lastIndexOf(strDouHao)>0) {
            stringBuilder.setLength(stringBuilder.length() - 1);
        }
        if(stringBuilder.length() == strOrderBy.length()) {
            stringBuilder.setLength(0);
        }

        return stringBuilder;
    }
}
